package com.issac.springbootredis.distributed_lock;

import com.issac.springbootredis.jedispool.Redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

/*
*
* 分布式锁
* pom.xml jedis依赖
* 一个问题：
*       当用户执行增删改等操作时，由于这三个操作不是原子性的，在多线程环境下会出问题。
* 解决思路:
*       占位，当一个操作进入redis中，其他操作会失败/暂缓操作，不会进入线程执行，
*             一般使用setnx方法进行占位，在业务操作结束后deL()释放
*
* */
public class DistributedLock {
    public static void main(String[] args) {
        Redis redis = new Redis();
        /*redis.exectue(jedis -> {
            //分布式锁方法1：缺点是 获取锁和加过期时间是两个操作，不具备原子性，假如在中间，服务器挂了，就会导致死锁
            Long setnx = jedis.setnx("k1", "v1");
            if (setnx == 1){
                //给锁加上一个过期时间，防止在业务代码执行过程中挂了 导致资源无法释放
                jedis.expire("k1",5);
                //线程无占位，执行操作
                jedis.set("name","傻逼");
                System.out.println(jedis.get("name"));
                //释放资源
                jedis.del("k1");
            }else {
                //线程占位，停止/暂缓操作
            }
        });*/

        redis.exectue(jedis -> {
            //分布式锁方法2：在redis2.8中，新增了setnx可以增加过期时间，让方法原子操作
            String set = jedis.set("k1", "v1", new SetParams().nx().ex(5));
            if (set != null && set.equals("OK")){
                //线程无占位，执行操作
                jedis.set("name","傻逼");
                System.out.println(jedis.get("name"));
                //释放资源
                jedis.del("k1");
            }else {
                //线程占位，停止/暂缓操作
            }
        });
    }

}
